package com.jsjvm.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.jsjvm.client.RemoteClassLoading;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class RemoteClassLoadingImpl extends RemoteServiceServlet implements
		RemoteClassLoading {
	private static final int MB = 1000 * 1000;
	private static final String PATH = "/home/ctalau/src/workspace/jsjvm/test-classes/";
	private static final String RT_PATH = "/usr/lib/jvm/java-6-openjdk/jre/lib/";
	private static final String RT_JAR = "rt.jar";

	public static final String[] CLASS_PATH = {
		PATH,
		RT_PATH,
	};
	
	private static byte [] readInputStream(InputStream is, int size) {
		byte ret [] = new byte[size];
		if (size > 10 * MB) return null;
		
		int off = 0, n;
		while (off < size){
			try {
				n = is.read(ret, off, size - off);
			} catch (IOException e) {
				return null;
			}
			off += n;
		}
		return ret;
	}

	private static byte[] readClassFromJar(String jarPath, String name){
		try {
			JarFile jf = new JarFile(new File(jarPath));
			JarEntry je = jf.getJarEntry(name);
			return readInputStream(jf.getInputStream(je), (int) je.getSize());
		} catch (Exception e) {
			return null;
		}
	}
	
	private static byte[] readClassFromFile(String path){
		File f = new File (path);
		try {
			return readInputStream(new FileInputStream(f), (int) f.length());
		} catch (Exception e) {
			System.out.println(e.getMessage());;
			return null;
		}
	}

	public static byte[] getClassBytes(String className) throws IllegalArgumentException {
		String path = PATH + className + ".class";
		byte[] data = readClassFromFile(path);
		if (data == null){
			data = readClassFromJar(RT_PATH + RT_JAR, className + ".class");
		}
		return data;
	}	
	
	public byte[] getClassFile(String className) throws IllegalArgumentException {
		return getClassBytes(className);
	}
}
